function Item(item) {
  this.id = item.id;
  this.type = item.type;
  this.title = item.title;
  this.text = item.text ? item.text : "No text yet.";
  switch (this.type) {
    case "info" :
      this.graphics = new Graphics(item.graphics ? JSON.parse(item.graphics) : { type : "atomic_models" });
      if (!this.graphics || !this.graphics.type) {
        var graphics = { type : this.graphics.type, options : this.graphics.options };
        this.saveProperty("graphics", JSON.stringify(graphics));
      }
      break;
    case "test" :
      this.task = new Task(this, item.task ? JSON.parse(item.task) : { type : "build_atom" });
      if (!this.task || !this.task.type) {
        var task = { type : this.task.type, options : this.task.options };
        this.saveProperty("task", JSON.stringify(task));
      }
      break;
    default :
      alert("unrecognized item type. item = " + JSON.stringify(item));
  }
}

Item.prototype = {
  show : function() {
    this.showTitle();
    this.showText();
    this.showOptions();
  },

  showTitle : function() {
    // defined by info and test classes
  },

  showText : function() {
    // defined by info and test classes
  },

  // called by tinyMCE when activated
  showSaveTextButton : function(e) {
    if (e.type == "mousedown") {
      $("#item #save_text").show();
    }
    return true;
  },


  edit : function(edit) {
    this.showOptions();

    var item = $("#item");
    item.title = item.find("#title");
    item.text = item.find("#text");

    item.title.find("span").html(this.title);
    if (tinymce) {
      tinymce.get("text").setContent(this.text);
    }

    switch (this.type) {
      case "info" :
        this.editInfo();
        break;
      case "test" :
        this.editTest();
        break;
    }
  },

  editTitle : function() {
    var val = prompt("Enter a new name for this item", this.title);
    if (val) {
      this.title = val;
      $.ajax({
        url : "/admin/edit_object?kind=item&id=" + this.id +
              "&property_name=title&property_value=" + val,
        type : "post",
        success : function() {
          lesson.edit();
        }
      });
    }
  },

  editInfo : function() {
    var item = $("#item");
    item.content = item.find(".content");
    item.options = item.find(".options")
    
    item.options.html();

    switch(this.graphics.type) {
      case "atomic_models" :
        this.graphics = new AtomicModels(this.graphics);
        break;
      case "electric_charge" :
        this.graphics = new ElectricCharge(this.graphics);
        break;
      default :
        alert("unrecognized graphics type. graphics = " + JSON.stringify(this.graphics));
    }
    this.graphics.edit();
  },

  editTest : function() {
    var item = $("#item");
    item.content = item.find(".content");
    item.options = item.find(".options");
    
    item.options.html();

    switch(this.task.type) {
      case "build_atom" :
        this.task = new BuildAtom(this, this.task);
        break;
      case "match_atoms" :
        this.task = new MatchAtoms(this, this.task);
        break;
      default :
        alert("unrecognized task type. task = " + JSON.stringify(this.task) + "\n" +
          "Reverting to default task type (\"build_atom\")");
        this.task.type = "build_atom";
        this.task = new BuildAtom(this, { options : { atom : "He-4" } });
    }
    this.task.edit();
  },

  showGraphics : function() {
    var item = $("#lesson #item-" + this.index);
    switch (this.graphics.type) {
      case "atomic_models" :
        var am = new AtomicModels(this.graphics);
        am.show(item);
        break;
      case "electric_charge" :
        var ec = new ElectricCharge(this.graphics);
        ec.show(item);
        break;
      default :
        alert("unrecognize graphics type. graphics = " + JSON.stringify(this.graphics));
    }
  },

  showOptions : function() {
    var options = $("#item .options");
    options.html("<div class='type f-right'></div><p class='large b'>Options</p><hr/>");
    options.type = options.find(".type");
    options.type.html("Item type : <select>" +
      "<option value='info'>info</option>" +
      "<option value='test'>test</option>" +
      "</select>");
    var os = options.type.find("option");
    for (var i = 0; i < os.length; i++) {
      if (os[i].value == this.type) {
        $(os[i]).attr("selected", "selected");
      }
    }
    options.type.find("select").change(function() {
      var item = lesson.items.current;
      item.type = this.value;
      switch (item.type) {
        case "info" : item.graphics = { type : "atomic_models" }; break;
        case "test" : item.task = { type : "build_atom" }; break;
        default : throw new Error("unrecognized item type"); break;
      }
      item.saveProperty("type", this.value);
      item.edit();
    });
  },

  saveProperty : function(property_name, property_value) {
    if (!property_value) {
      property_value = JSON.stringify(this[property_name]);
    }
    $.ajax({
      url : "/admin/edit_object?kind=item&id=" + this.id +
        "&property_name=" + property_name + "&property_value=" + property_value,
      type : "post",
      success : function() {
//          alert("success!");
      }
    });
  },

  showTask : function(target) {
    var task;
    switch (this.task.type) {
      case "build_atom"  :
        task = new BuildAtom(this.task);
        break;
      case "match_atoms" :
        task = new MatchAtoms(this.task);
        break;
      default : 
        throw new Error("unrecognized task type. graphics = " + JSON.stringify(this.task));
    }
    return task.show(target);
  },

  saveTitle : function(title) {
    this.saveProperty("title", title);
  },  

  saveText : function(text) {
    $("#item #save_text").hide();
    this.saveProperty("text", text);
  }
};

function Graphics(graphics) {
  if (graphics && graphics.type) {
    this.type = graphics.type;
    if (graphics.options) {
      this.options = graphics.options;
    }
  } else {
    this.type = "atomic_models";
    this.options = { atoms : ["C-12"], labels : [] };
  }
  switch (this.type) {
    case "atomic_models" :
      if (typeof(AtomicModels) != "undefined") {
        return new AtomicModels(this);
      }
      break;
    case "electric_charge" :
      if (typeof(ElectricCharge) != "undefined") {
        return new ElectricCharge(this);
      }
      break;
    default :
      throw new Error("unrecognized graphics type. graphics = " + JSON.stringify(graphics));
  }
}

Graphics.prototype = {
  show : function(target) {

  },

  showOptions : function() {
    var options = $("#item .options");
    if (options.find(".graphics-type").length == 0) {
      options.append("<div class='graphics-type'></div>");
    }
    options.find(".graphics-type").html("Graphics type : <select>" +
      "<option value='atomic_models'>Atomic Models</option>" +
      "<option value='electric_charge'>Electric Charge</options>" +
      "</select>");
    for (var i = 0; i < options.find(".graphics-type option").length; i++) {
      var option = $(options.find(".graphics-type option")[i]);
      if (option.val() == this.type) {
        option.attr("selected", "selected");
      }
    }
    options.find(".graphics-type select").change(function() {
      var item = lesson.items.current;
      item.graphics.type = this.value;
      item.saveProperty("graphics", JSON.stringify({ type : item.graphics.type }));
      item.edit();
    });
  }
};

function Task(item, task) {
  if (task && task.type) {
    this.type = task.type;
    if (task.options) {
      this.options = task.options;
    }
  } else {
    this.type = "build_atom";
    this.options = { atom : ["He-4"] };
  }
  switch (this.type) {
    case "build_atom" :
      if (typeof(BuildAtom) != "undefined") {
        return new BuildAtom(item, this);
      }
      break;
    case "match_atoms" :
      if (typeof(MatchAtoms) != "undefined") {
        return new MatchAtoms(item, this);
      }
      break;
    default :
      throw new Error("unrecognized task type. task = " + JSON.stringify(task));
  }
}

Task.prototype = {
  mouse : { down : false, target : null, z : 16 },
  
  show : function(target) {
    if (!target) {
      target = this.target ? this.target : $("#item .content");
    } else {
      this.target = target;
    }
    target.html("<div class='" + this.type + "'></div>");
    this.target = target;
    this.easel = target.find("." + this.type);


    var data = { task : this };
    var c = this.easel.find("canvas");
    c.mousedown(data, function(event) { event.data.task.canvasMouseDown(event) });
    c.mouseup(data, function(event) { event.data.task.canvasMouseUp(event) });
  },

  showOptions : function() {
    var options = $("#item .options");
    if (options.find(".task-type").length == 0) {
      options.append("<div class='task-type'></div>");
    }
    options.find(".task-type").html("Task type : <select>" +
      "<option value='build_atom'>Build Atom</option>" +
      "<option value='match_atoms'>Match Atoms</options>" +
      "</select>");
    for (var i = 0; i < options.find(".task-type option").length; i++) {
      var option = $(options.find(".task-type option")[i]);
      if (option.val() == this.type) {
        option.attr("selected", "selected");
      }
    }
    options.find(".task-type select").change(function() {
      var item = lesson.items.current;
      item.task.type = this.value;
      item.saveProperty("task", JSON.stringify({ type : item.task.type }));
      item.edit();
    });
  },

  showScore : function(score) {
    if (this.easel.find(".score").length == 0) {
      this.easel.append("<div class='score p-absolute border-1 a-left'></div>");
    }
    this.easel.score = this.easel.find(".score");
  },

  recordScore : function(score) {
    score.lesson_id = lesson.id;
    score.item_id = this.parent.id;
    $.ajax({
      url : "/score/record?score=" + JSON.stringify(score),
      type : "POST"
    });
  },

  canvasMouseDown : function() {},
  canvasMouseUp : function() {},

  enableScoreButton : function() {
    var sb = this.easel.find(".score-button");
    if (sb.length > 0) {
      sb.attr("enabled", "true");
      sb.find("img")[0].src = "/images/apply.png";
    }
  },

  disableScoreButton : function() {
    this.easel.find(".score-button").attr("enabled", "false");
    this.easel.find(".score-button img")[0].src = "/images/apply_gray.png";
  }
};